package com.lijian.study.mongo.component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.UUID;

import org.springframework.stereotype.Component;

import com.github.javafaker.Faker;
import com.lijian.study.mongo.Entity.Address;
import com.lijian.study.mongo.Entity.Role;
import com.lijian.study.mongo.Entity.User;
import com.lijian.study.mongo.repository.AddressRepository;
import com.lijian.study.mongo.repository.RoleRepository;
import com.lijian.study.mongo.repository.UserRepository;

@Component
public class DataLoader {

    private final UserRepository userRepository;
    private final AddressRepository addressRepository;
    private final RoleRepository roleRepository;

    private final Faker faker = new Faker(new Locale("zh-CN")); // 创建中文Faker实例

    private final Random random = new Random();

    public DataLoader(UserRepository userRepository, AddressRepository addressRepository,
            RoleRepository roleRepository) {
        this.userRepository = userRepository;
        this.addressRepository = addressRepository;
        this.roleRepository = roleRepository;
    }

    public void run() throws Exception {
        // 清空数据库
        userRepository.deleteAll();
        addressRepository.deleteAll();
        roleRepository.deleteAll();

        // 生成角色
        List<Role> roles = generateRoles(5);
        roleRepository.saveAll(roles);

        // 生成地址
        List<Address> addresses = generateAddresses(5);
        addressRepository.saveAll(addresses);

        // 生成用户及其地址
        List<User> users = generateUsers(20, roles, addresses);
        userRepository.saveAll(users);
    }

    private List<Role> generateRoles(int count) {
        List<Role> roles = new ArrayList<>();
        for (int i = 1; i <= count; i++) {
            roles.add(Role.builder().id(UUID.randomUUID().toString())
                    .roleName(faker.job().title()) // 使用 Faker 生成中文角色名
                    .build());
        }
        return roles;
    }

    private List<User> generateUsers(int userCount, List<Role> roles, List<Address> addresses) {
        List<User> users = new ArrayList<>();
        for (int i = 1; i <= userCount; i++) {
            // List<Address> addresses = generateAddresses(random.nextInt(3) + 1); // 每个用户 1
            // 到 3 个地址
            User user = User.builder().id(UUID.randomUUID().toString())
                    .createdDate(LocalDateTime.now())
                    // .lastModifiedDate(LocalDateTime.now()) // 这个会自动填充
                    .name(faker.name().fullName()) // 使用 Faker 生成中文姓名
                    .email(faker.internet().emailAddress()) // 使用 Faker 生成电子邮件
                    .addresses(getRandomAddresses(addresses, 2))
                    .roles(getRandomRoles(roles, 2)) // 随机选择2个角色
                    .build();
            users.add(user);
        }
        return users;
    }

    private List<Address> generateAddresses(int count) {
        List<Address> addresses = new ArrayList<>();
        for (int i = 1; i <= count; i++) {
            addresses.add(Address.builder().id(UUID.randomUUID().toString())
                    .street(faker.address().streetAddress()) // 使用 Faker 生成中文地址
                    .city(faker.address().city())
                    .state(faker.address().state())
                    .zipCode(faker.address().zipCode())
                    .build());
        }
        return addresses;
    }

    private List<Role> getRandomRoles(List<Role> roles, int count) {
        List<Role> selectedRoles = new ArrayList<>();
        while (selectedRoles.size() < count) {
            Role randomRole = roles.get(random.nextInt(roles.size()));
            if (!selectedRoles.contains(randomRole)) {
                selectedRoles.add(randomRole);
            }
        }
        return selectedRoles;
    }

    private List<Address> getRandomAddresses(List<Address> addresses, int count) {
        List<Address> selectedAddresses = new ArrayList<>();
        while (selectedAddresses.size() < count) {
            Address address = addresses.get(random.nextInt(addresses.size()));
            if (!selectedAddresses.contains(address)) {
                selectedAddresses.add(address);
            }
        }
        return selectedAddresses;
    }
}
